﻿namespace DslEditorPowerToy.Controls.Languages
{
    using DslEditorPowerToy.Controls;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Modeling.Shell;
    using Microsoft.VisualStudio.Shell.Interop;
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;

    internal class ComponentSelectionBroker : IDisposable, ISelectionService, ISelectionContainer
    {
        private Component _component;
        private ModelingDocView _docView;
        private object _primarySelection;
        private ArrayList _selectedItems = new ArrayList();
        private IHelpService _selectionHelpService;
        private IServiceProvider _serviceProvider;

        public event SelectionChangedEventHandler EnvironmentSelectionChanged;

        public event EventHandler SelectionChanged;

        public event EventHandler SelectionChanging;

        public ComponentSelectionBroker(IServiceProvider serviceProvider, Component component)
        {
            this._serviceProvider = serviceProvider;
            this._component = component;
            this.Initialise();
        }

        private void Control_SelectionChanged(object sender, EventArgs e)
        {
            if ((this._component != null) && (this._component is ISelectionService))
            {
                this.SetSelectedComponentsInternal((this._component as ISelectionService).GetSelectedComponents());
            }
        }

        public int CountObjects(uint flags, out uint count)
        {
            count = 0;
            if ((1 == (flags & 1)) || (2 == (flags & 2)))
            {
                count = (uint) this._selectedItems.Count;
            }
            return 0;
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if ((this._component != null) && (this._component is ISelectionService))
                {
                    ((ISelectionService) this._component).SelectionChanged -= new EventHandler(this.Control_SelectionChanged);
                }
                if (this._docView != null)
                {
                    this._docView.SelectionChanged -= new EventHandler(this.OnDocViewSelectionChanged);
                }
                if (this._serviceProvider != null)
                {
                    IMonitorSelectionService service = this._serviceProvider.GetService(typeof(IMonitorSelectionService)) as IMonitorSelectionService;
                    if (service != null)
                    {
                        service.SelectionChanged -= new EventHandler<MonitorSelectionEventArgs>(this.OnMonitorSelectionSeviceSelectionChanged);
                    }
                }
            }
        }

        ~ComponentSelectionBroker()
        {
            this.Dispose(false);
        }

        public bool GetComponentSelected(object component)
        {
            for (int i = 0; i < this._selectedItems.Count; i++)
            {
                if (component == this._selectedItems[i])
                {
                    return true;
                }
            }
            return false;
        }

        public int GetObjects(uint flags, uint count, object[] objects)
        {
            if ((1 == (flags & 1)) || (2 == (flags & 2)))
            {
                IList list = this._selectedItems;
                if (count <= list.Count)
                {
                    list.CopyTo(objects, 0);
                }
            }
            return 0;
        }

        public ICollection GetSelectedComponents()
        {
            return ArrayList.ReadOnly(this._selectedItems);
        }

        private IHelpService GetSelectionHelpService()
        {
            if (this._selectionHelpService == null)
            {
                IHelpService service = (IHelpService) this._serviceProvider.GetService(typeof(IHelpService));
                if (service != null)
                {
                    this._selectionHelpService = service.CreateLocalContext(HelpContextType.Selection);
                }
            }
            return this._selectionHelpService;
        }

        private void Initialise()
        {
            if (this._serviceProvider != null)
            {
                IMonitorSelectionService service = this._serviceProvider.GetService(typeof(IMonitorSelectionService)) as IMonitorSelectionService;
                if (service != null)
                {
                    service.SelectionChanged += new EventHandler<MonitorSelectionEventArgs>(this.OnMonitorSelectionSeviceSelectionChanged);
                }
            }
            if ((this._component != null) && (this._component is ISelectionService))
            {
                ((ISelectionService) this._component).SelectionChanged += new EventHandler(this.Control_SelectionChanged);
            }
        }

        private bool IsSameAsCache(ICollection selectedComponents)
        {
            int num = (selectedComponents != null) ? selectedComponents.Count : 0;
            bool flag = this._selectedItems.Count != num;
            if (!flag && (selectedComponents != null))
            {
                foreach (object obj2 in selectedComponents)
                {
                    flag = !this._selectedItems.Contains(obj2);
                    if (flag)
                    {
                        break;
                    }
                }
            }
            return !flag;
        }

        private void OnDocViewSelectionChanged(object sender, EventArgs e)
        {
            ISelectionService service = this._docView;
            if (service != null)
            {
                this.OnSelectionChanged(new SelectionProvider(service), SelectionChangeSource.Diagram);
            }
        }

        private void OnMonitorSelectionSeviceSelectionChanged(object sender, MonitorSelectionEventArgs e)
        {
            ISelectionService newValue = e.NewValue as ISelectionService;
            if (newValue != null)
            {
                this.OnSelectionChanged(new SelectionProvider(newValue), SelectionChangeSource.Environment);
            }
            else
            {
                ISelectionContainer container = e.NewValue as ISelectionContainer;
                if (container != null)
                {
                    this.OnSelectionChanged(new SelectionProvider(container), SelectionChangeSource.Environment);
                }
            }
        }

        protected void OnSelectionChanged()
        {
            if (this.SelectionChanged != null)
            {
                this.SelectionChanged(this, new EventArgs());
            }
        }

        private void OnSelectionChanged(ISelectionProvider selectionProvider, SelectionChangeSource source)
        {
            if (this.EnvironmentSelectionChanged != null)
            {
                this.EnvironmentSelectionChanged(this, new SelectionChangedEventArgs(selectionProvider, source));
            }
            if ((this._component != null) && (this._component is IMonitorSelection))
            {
                ((IMonitorSelection) this._component).NotifySelectionChanged(selectionProvider, source);
            }
        }

        protected void OnSelectionChanging()
        {
            if (this.SelectionChanging != null)
            {
                this.SelectionChanging(this, new EventArgs());
            }
        }

        public void RegisterDocView(ModelingDocView docView)
        {
            if (docView != null)
            {
                if (this._docView != null)
                {
                    this._docView.SelectionChanged -= new EventHandler(this.OnDocViewSelectionChanged);
                }
                this._docView = docView;
                docView.SelectionChanged += new EventHandler(this.OnDocViewSelectionChanged);
            }
        }

        public int SelectObjects(uint cSelect, object[] apUnkSelect, uint dwFlags)
        {
            return 0;
        }

        public void SetSelectedComponents(ICollection components)
        {
            this.SetSelectedComponentsInternal(components);
        }

        public void SetSelectedComponents(ICollection components, SelectionTypes selectionType)
        {
            throw new NotImplementedException();
        }

        private void SetSelectedComponentsInternal(ICollection selectedComponents)
        {
            if (!this.IsSameAsCache(selectedComponents))
            {
                this.OnSelectionChanging();
                this._selectedItems.Clear();
                if (selectedComponents != null)
                {
                    IList list = this._selectedItems;
                    foreach (object obj2 in selectedComponents)
                    {
                        list.Add(obj2);
                    }
                }
                if ((this._primarySelection != null) && !this._selectedItems.Contains(this._primarySelection))
                {
                    this._primarySelection = null;
                }
                IVsTrackSelectionEx service = (IVsTrackSelectionEx) this._serviceProvider.GetService(typeof(IVsTrackSelectionEx));
                if (service != null)
                {
                    ErrorHandler.ThrowOnFailure(service.OnSelectChange(this));
                }
                if (this._selectionHelpService != null)
                {
                    this._selectionHelpService.ClearContextAttributes();
                }
                this.OnSelectionChanged();
            }
        }

        public object PrimarySelection
        {
            get
            {
                if (this._primarySelection != null)
                {
                    return this._primarySelection;
                }
                if (this._selectedItems.Count > 0)
                {
                    return this._selectedItems[0];
                }
                return null;
            }
            set
            {
                this._primarySelection = value;
            }
        }

        public int SelectionCount
        {
            get
            {
                return this._selectedItems.Count;
            }
        }
    }
}

